from enum import StrEnum

from sqlalchemy import func
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapped, mapped_column
from core.file.helpers import get_signed_file_url
from models.engine import db
from models.online_mall.prod_other import MProductTag, MProductTagProduct
from models.types import StringUUID


class ProdcutStatus(StrEnum):
    NORMAL = "N"
    DELETED = "D"
    PUTAWAY = "P"
    OUT_OF_STOCK = "O" # 下架
    @staticmethod
    def choices()->list[str]:
        return ["N","D","P","O"]
class MProdSKU(db.Model):
    __tablename__ = "sp_prod_sku"
    __table_args__ = (
        db.PrimaryKeyConstraint("id", name="sp_prod_sku_pkey"),
        db.Index("sp_prod_sku_prod_id_idx", "prod_id"),
    )
    id: Mapped[str] = mapped_column(StringUUID, server_default=db.text("uuid_generate_v4()"), primary_key=True)
    prod_id = db.Column(StringUUID, nullable=False,comment="产品ID")
    properties = db.Column(JSONB, nullable=True,server_default=db.text("'{}'::jsonb") ,comment="属性")
    ori_price = db.Column(db.Integer, nullable=False,comment="原价")
    price = db.Column(db.Integer, nullable=False,comment="价格")
    stocks = db.Column(db.Integer, nullable=False,comment="商品在付款减库存的状态下，该sku上未付款的订单数量")
    actual_stocks = db.Column(db.Integer, nullable=False,comment="实际库存")
    created_at = db.Column(db.TIMESTAMP(timezone=False),server_default=func.current_timestamp(), nullable=False,comment="创建时间")
    created_by = db.Column(StringUUID, nullable=False,comment="创建人")
    updated_at = db.Column(db.TIMESTAMP(timezone=False), nullable=True,comment="更新时间")
    updated_by = db.Column(StringUUID, nullable=True,comment="更新人")
    party_code = db.Column(db.String(128), nullable=True,comment="商家货号")
    model_code = db.Column(db.String(128), nullable=True,comment="商品条形码")
    pic_file_id = db.Column(StringUUID, nullable=True,comment="图片文件ID")
    sku_name = db.Column(db.String(128), nullable=True,comment="sku名称")
    prod_name = db.Column(db.String(255), nullable=True,comment="商品名称")
    weight = db.Column(db.Float(precision=24, decimal_return_scale=8), nullable=True,comment="重量")
    volume = db.Column(db.Float(precision=24, decimal_return_scale=8), nullable=True,comment="体积")
    status = db.Column(db.Boolean, server_default=db.text("true"), nullable=False,comment="sku是否启用")
    is_deleted = db.Column(db.Boolean, server_default=db.text("false"), nullable=False,comment="是否删除")

    @property
    def OriPrice(self)->float|None:
        if self.ori_price:
            return self.ori_price*(1/1000)
        return None
    
    @OriPrice.setter
    def OriPrice(self,value:float):
        if value:
            self.ori_price = int(value*1000)
        else:
            self.ori_price = None
    
    @property
    def Price(self)->float|None:
        if self.price:
            return self.price*(1/1000)
        return None
    
    @Price.setter
    def Price(self,value:float):
        if value:
            self.price = int(value*1000)
        else:
            self.price = None

    @property
    def PicFileUrl(self)->str|None:
        if self.pic_file_id:
            return get_signed_file_url(self.pic_file_id)
        return None

class MCart(db.Model):
    __tablename__ = "sp_cart"
    __table_args__ = (
        db.PrimaryKeyConstraint("id", name="sp_cart_pkey"),
        db.Index("sp_cart_account_id_idx", "account_id"),
        db.Index("sp_cart_shop_id_idx", "shop_id"),
        db.UniqueConstraint("account_id", "shop_id", "sku_id", name="sp_cart_account_id_shop_id_sku_id_key")
    )
    id = db.Column(db.BigInteger, primary_key=True, autoincrement=True,comment="ID")
    account_id = db.Column(StringUUID, nullable=False,comment="账号ID")
    shop_id = db.Column(StringUUID, nullable=False,comment="店铺ID")
    prod_id = db.Column(StringUUID, nullable=False,comment="商品ID")
    sku_id = db.Column(StringUUID, nullable=False,comment="SKU ID")
    count = db.Column(db.Integer, nullable=False,default=db.text('0'),comment="购物车产品个数")
    shop_at = db.Column(db.TIMESTAMP(timezone=False),server_default=func.current_timestamp(), nullable=False,comment="创建时间")
    discount_id = db.Column(db.BigInteger, nullable=True,comment="优惠券/满减活动ID")
    ip_addr = db.Column(db.String(32), nullable=False,comment="IP地址")
    distribution_card_no = db.Column(db.String(32), nullable=True,comment="分销推广人卡号")


class MProduct(db.Model):
    __tablename__ = "sp_prod"
    __table_args__ = (
        db.PrimaryKeyConstraint("id", name="sp_product_pkey"),
        db.Index("sp_product_shop_id_idx", "shop_id"),
        db.Index("sp_product_status_idx", "status"),
        db.Index("sp_product_name_idx", "name"),
        db.Index("sp_product_category_id_idx", "category_id"),
    )
    id: Mapped[str] = mapped_column(StringUUID, server_default=db.text("uuid_generate_v4()"))
    name = db.Column(db.String(255), nullable=False,comment="商品名称")
    shop_id = db.Column(StringUUID, nullable=False,comment="店铺ID")
    ori_price = db.Column(db.Integer, nullable=False,comment="原价")
    price = db.Column(db.Integer, nullable=False,server_default=db.text('0'),comment="售价")
    brief = db.Column(db.String(512), nullable=True,server_default=db.text("''"),comment="商品简介")
    content = db.Column(db.Text, nullable=True,comment="商品详情")
    pic_file_id = db.Column(StringUUID, nullable=True,comment="商品主图片文件ID")
    imgs = db.Column(JSONB, nullable=True,server_default=db.text("'{}'::jsonb"),comment="商品图片items")
    status = db.Column(db.String(1),server_default=db.text("'N'::character varying"), nullable=False,comment="商品状态")
    category_id = db.Column(StringUUID, nullable=True,comment="商品分类ID")
    sold_num = db.Column(db.Integer, nullable=True,server_default=db.text('0'), comment="商品已售数量")
    total_stocks = db.Column(db.Integer, nullable=True,server_default=db.text('0'), comment="商品总库存")
    delivery_mode = db.Column(JSONB, nullable=True,server_default=db.text("'{}'::jsonb"),comment="配送方式")
    delivery_template_id = db.Column(db.BigInteger, nullable=True,comment="配送模板ID")
    putaway_at = db.Column(db.TIMESTAMP(timezone=False),server_default=func.current_timestamp(), nullable=False,comment="上架时间")
    ver = db.Column(db.BigInteger, nullable=True,server_default=db.text('0'),comment="版本号锁")
    created_at = db.Column(db.TIMESTAMP(timezone=False),server_default=func.current_timestamp(), nullable=False,comment="创建时间")
    created_by = db.Column(StringUUID, nullable=False,comment="创建人")
    updated_at = db.Column(db.TIMESTAMP(timezone=False), nullable=True,comment="更新时间")
    updated_by = db.Column(StringUUID, nullable=True,comment="更新人")

    @property
    def ImageIds(self)->list[str]:
        if self.imgs and 'items' in self.imgs:
            return self.imgs.get('items',[])
        return []
    
    @ImageIds.setter
    def ImageIds(self,image_ids:list[str]):
        if self.imgs:
            self.imgs['items'] = image_ids
        else:
            self.imgs = {"items":image_ids}

    @property
    def ImageUrls(self)->list[str]:
        if self.imgs and 'items' in self.imgs:
            urls = []
            items = self.imgs.get('items',[])
            for item in items:
                urls.append(get_signed_file_url(item))
            return urls
        return []

    @property
    def OriPrice(self)->float|None:
        if self.ori_price:
            return self.ori_price*(1/1000)
        return None
    
    @OriPrice.setter
    def OriPrice(self,value:float):
        if value:
            self.ori_price = int(value*1000)
        else:
            self.ori_price = None
    
    @property
    def Price(self)->float|None:
        if self.price:
            return self.price*(1/1000)
        return None
    
    @Price.setter
    def Price(self,value:float):
        if value:
            self.price = int(value*1000)
        else:
            self.price = None

    @property
    def PicFileUrl(self)->str|None:
        if self.pic_file_id:
            return get_signed_file_url(self.pic_file_id)
        return None
    
    @property
    def hasUserPickUp(self)->bool:
        """
        是否用户自提
        """
        if self.delivery_mode:
            return self.delivery_mode.get("hasUserPickUp",False)
        return False
    
    @hasUserPickUp.setter
    def hasUserPickUp(self,value:bool):
        if self.delivery_mode:
            self.delivery_mode["hasUserPickUp"] = value
        else:
            self.delivery_mode = {"hasUserPickUp":value}

    @property
    def hasShopDelivery(self)->bool:
        """
        是否商家配送
        """
        if self.delivery_mode:
            return self.delivery_mode.get("hasShopDelivery",False)
        return False
    
    @hasShopDelivery.setter
    def hasShopDelivery(self,value:bool):
        if self.delivery_mode:
            self.delivery_mode["hasShopDelivery"] = value
        else:
            self.delivery_mode = {"hasShopDelivery":value}

    @property
    def sku_list(self)->list[MProdSKU]:
        """
        商品SKU列表
        """
        return db.session.query(MProdSKU).filter(MProdSKU.prod_id==self.id).all()

    @property
    def tag_list(self)->list[MProductTag]:
        """
        商品标签列表
        """
        return db.session.query(MProductTag).join(MProductTagProduct,
                                           (MProductTagProduct.tag_id==MProductTag.id)&
                                           (MProductTagProduct.prod_id==self.id)&
                                           (MProductTagProduct.shop_id==self.shop_id)).all()
